#include <jni.h>
#include "../perseus.h"
#include "PerseusJni.h"

JNIEXPORT jlong JNICALL Java_Perseus_perseusAlloc(JNIEnv *env, jclass cls)
{
   libperseus_hl_t *lhl = calloc( 1, sizeof( libperseus_hl_t ) );

#ifdef DEBUG
   printf("[native][perseusAlloc] LHL @ 0x%lx\n", (unsigned long)(lhl));
#endif

   return (jlong)(long)lhl;   
}

JNIEXPORT jint JNICALL Java_Perseus_perseusInit(JNIEnv *env, jclass cls, jlong addr, jfloat a1, jfloat a2, jfloat a3, jfloat a4)
{
   int ret;
   libperseus_hl_t *lhl = (libperseus_hl_t *)((unsigned long)(addr));

#ifdef DEBUG
   printf("[native][perseusInit) LHL @ 0x%lx %f %f %f %f\n", (unsigned long)lhl, (float)(a1), (float)(a2), (float)(a3), (float)(a4));
#endif

   ret = perseus_init( lhl, (float)(a1), (float)(a2), (float)(a3), (float)(a4) );

   return (jint)ret;
}


JNIEXPORT jcharArray JNICALL Java_Perseus_perseusCode(JNIEnv *env, jclass cls, jlong addr, jcharArray data)
{
   int i;
   unsigned long int encoded_data_size;
   unsigned char *native_data;
   unsigned char *encoded_data;
   int data_size;

   jcharArray resul;

   libperseus_hl_t *lhl = (libperseus_hl_t *)((unsigned long)(addr));
   data_size = (*env)->GetArrayLength(env, data);

   jchar *d = (*env)->GetCharArrayElements(env, data, NULL); 

   native_data = calloc( 1, data_size );
   for (i = 0; i < data_size; i++)  
      {  
             native_data[i] = (char)d[i];
      }  

   free(d);

#ifdef DEBUG
   printf("[native][encoded] %d\n", data_size);
#endif

   encoded_data = perseus_code( lhl, native_data, data_size, &encoded_data_size );

#ifdef DEBUG
   printf("[native][encoded] --> 0x%lx %d\n", (unsigned long)(encoded_data), (int)encoded_data_size);
#endif

   d = (jchar *)calloc(sizeof(jchar), encoded_data_size );
   for (i = 0; i < encoded_data_size; i++)
      {
         d[i] = (jchar)(encoded_data[i]);
      }

   resul = (*env)->NewCharArray(env, encoded_data_size);
   (*env)->SetCharArrayRegion(env, resul, 0, encoded_data_size, d);

   free( native_data );
   free( encoded_data );
   free( d );

   return resul;
}

JNIEXPORT jcharArray JNICALL Java_Perseus_perseusDecode(JNIEnv *env, jclass cls, jlong addr, jcharArray data)
{
   int i;
   unsigned long int decoded_data_size;
   unsigned char *native_data;
   unsigned char *decoded_data;
   int data_size;

   jcharArray resul;

   libperseus_hl_t *lhl = (libperseus_hl_t *)((unsigned long)(addr));
   data_size = (*env)->GetArrayLength(env, data);

   jchar *d = (*env)->GetCharArrayElements(env, data, NULL); 

   native_data = calloc( 1, data_size );
   for (i = 0; i < data_size; i++)  
      {  
             native_data[i] = (char)d[i];
      }  

   free( d );

#ifdef DEBUG
   printf("[native][decoded] %d\n", data_size);
#endif

   decoded_data = perseus_decode( lhl, native_data, data_size, &decoded_data_size );

#ifdef DEBUG
   printf("[native][decoded] --> 0x%lx %d\n", (unsigned long)(decoded_data), (int)decoded_data_size);
#endif

   d = (jchar *)calloc(sizeof(jchar), decoded_data_size );
   for (i = 0; i < decoded_data_size; i++)
      {
         d[i] = (jchar)(decoded_data[i]);
      }

   resul = (*env)->NewCharArray(env, decoded_data_size);
   (*env)->SetCharArrayRegion(env, resul, 0, decoded_data_size, d);

   free( native_data );
   free( decoded_data );
   free( d );

   return resul;
}

JNIEXPORT void JNICALL Java_Perseus_perseusDestroy(JNIEnv *env, jobject cls, jlong addr) {
   libperseus_hl_t *lhl = (libperseus_hl_t *)((unsigned long)(addr));

   perseus_destroy( lhl );
}

